package com.yami.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.bo.PlatformCommissionOrderItemBO;
import com.yami.shop.bean.dto.ExchangeOrderDTO;
import com.yami.shop.bean.dto.RedOrderDto;
import com.yami.shop.bean.enums.*;
import com.yami.shop.bean.event.*;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.param.OrderParam;
import com.yami.shop.bean.vo.OrderAmountVO;
import com.yami.shop.bean.vo.UnDeliveryOrderExcelVO;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.enums.PayType;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.i18n.I18nMessage;
import com.yami.shop.common.util.*;
import com.yami.shop.dao.*;
import com.yami.shop.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

import static com.yami.shop.bean.enums.OrderType.RED;
import static com.yami.shop.bean.enums.ReturnMoneyStsType.SUCCESS;

/**
 * @author lgh on 2018/09/15.
 */
@Slf4j
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Value("${yami.expose.operation.auth:}")
    private Boolean permission;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private DeliveryService orderDeliverService;
    @Autowired
    private NotifyTemplateService notifyTemplateService;
    @Autowired
    private StationService stationService;
    @Autowired
    private OrderItemService orderItemService;
    @Autowired
    private OrderSettlementService orderSettlementService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    private OrderLangMapper orderlangMapper;
    @Autowired
    private OrderRefundMapper orderRefundMapper;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private OrderVirtualInfoService orderVirtualInfoService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private SkuStockLockService skuStockLockService;
    @Autowired
    private PayInfoMapper payInfoMapper;
    @Autowired
    private Snowflake snowflake;
    @Autowired
    private ProductService productService;
    @Autowired
    private UserAddrService userAddrService;
    @Autowired
    private OrderSettlementMapper orderSettlementMapper;

    @Override
    public Order getOrderByOrderNumber(String orderNumber) {
        return orderMapper.getOrderByOrderNumber(orderNumber);
    }

    @Override
    public Order getOrderByOrderNumberAndUserId(String orderNumber, String userId, boolean valid) {
        Order order = orderMapper.getOrderByOrderNumberAndUserId(orderNumber, userId);
        if (valid && Objects.isNull(order)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        return order;
    }

    @Override
    public Order getOrderByOrderNumberAndShopId(String orderNumber, Long shopId, boolean valid) {
        Order order = orderMapper.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNumber, orderNumber).eq(Order::getShopId, shopId));
        if (valid && order == null) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        return order;
    }


    @Override
    @CacheEvict(cacheNames = "ConfirmOrderCache", key = "#userId")
    public void removeConfirmOrderCache(String userId) {
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Order> submit(ShopCartOrderMergerDto mergerOrder) {
        String userId = mergerOrder.getUserId();
        // 扣减商品库存，本次下单使用的优惠券、积分
        TryLockStockEvent tryLockStockEvent = new TryLockStockEvent(mergerOrder, userId);
        eventPublisher.publishEvent(tryLockStockEvent);
        mergerOrder.setProdList(tryLockStockEvent.getProdList());
        List<Order> orderList = new ArrayList<>();
        // 提交订单
        eventPublisher.publishEvent(new SubmitOrderEvent(mergerOrder, orderList));
        List<OrderItem> orderItems = orderList.stream().flatMap(order -> order.getOrderItems().stream()).collect(Collectors.toList());

        // 预售订单获取优先购权益ID
        if (Objects.equals(mergerOrder.getOrderType(), OrderType.PRESELL)) {
            eventPublisher.publishEvent(new SubmitOrderQualificationEvent(mergerOrder, orderItems, 2));
        }

        //calculatePlatformCommission(orderList, orderItems);
        // 插入订单
        saveBatch(orderList);
        // 保存订单语言表
        // orderlangMapper.insertBatchOrderLang(orderList);
        // 插入订单项，返回主键
        orderItemService.insertBatchOrderItem(orderItems);
        // 只有普通商品才需要处理赠品
        if (Objects.equals(mergerOrder.getOrderType(), OrderType.ORDINARY)) {
            // 添加赠品
            eventPublisher.publishEvent(new SubmitOrderGiveawayEvent(orderList, orderItems));
        }
//        //计算积分情况
//        if (mergerOrder.getIsScorePay() != null && mergerOrder.getIsScorePay() == 1) {
//            eventPublisher.publishEvent(new SubmitScoreOrderEvent(mergerOrder, orderList));
//        }
//        List<String> orderNumbers = new ArrayList<>();
//        orderList.forEach(order -> orderNumbers.add(order.getOrderNumber()));
//        // 发送消息，如果三十分钟后没有支付，则取消订单
//        SendStatus sendStatus = orderCancelTemplate.syncSend(RocketMqConstant.ORDER_CANCEL_TOPIC, new GenericMessage<>(orderNumbers), RocketMqConstant.TIMEOUT, RocketMqConstant.CANCEL_ORDER_DELAY_LEVEL).getSendStatus();
//        if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
//            // 消息发不出去就抛异常，发的出去无所谓
//            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
//        }
        return orderList;
    }

    /**
     * 计算分摊金额
     */
    private void calculatePlatformCommission(List<Order> orders, List<OrderItem> orderItems) {
        boolean scoreOrder = Objects.equals(orders.get(0).getOrderType(), OrderType.SCORE.value());
        List<PlatformCommissionOrderItemBO> platformCommissionOrderItems = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            PlatformCommissionOrderItemBO platformCommissionOrderItemBO = new PlatformCommissionOrderItemBO();
            platformCommissionOrderItemBO.setShopId(orderItem.getShopId());
            platformCommissionOrderItemBO.setCategoryId(orderItem.getCategoryId());
            platformCommissionOrderItemBO.setSkuId(orderItem.getSkuId());
            platformCommissionOrderItems.add(platformCommissionOrderItemBO);
        }
        // 获取整个平台的佣金比例
        List<Category> categoryRates = categoryService.listRate();
        List<PlatformCommissionOrderItemBO> data = categoryService.calculatePlatformCommission(platformCommissionOrderItems, categoryRates);
        for (OrderItem orderItem : orderItems) {
            for (PlatformCommissionOrderItemBO platformCommissionOrderItemBO : data) {
                double platformCommission = 0.0;
                // 积分订单属于平台的订单不需要计算平台佣金
                if (scoreOrder) {
                    orderItem.setPlatformCommission(platformCommission);
                    continue;
                }
                // 通过商品确定订单项
                if (Objects.equals(orderItem.getSkuId(), platformCommissionOrderItemBO.getSkuId())) {
                    // 分摊比例
                    orderItem.setRate(platformCommissionOrderItemBO.getRate());
                    // 平台佣金 = （实付金额 + 平台优惠金额） * 比例 / 100
                    platformCommission = Arith.roundByBanker(Arith.div(Arith.mul(Arith.add(orderItem.getActualTotal(), orderItem.getPlatformShareReduce()),
                            platformCommissionOrderItemBO.getRate()), 100), 2);
                    orderItem.setPlatformCommission(platformCommission);
                }
            }
        }
        Map<String, List<OrderItem>> orderNumberMap = orderItems.stream().collect(Collectors.groupingBy(OrderItem::getOrderNumber));
        for (Order order : orders) {
            double totalPlatformCommission = 0.0;
            List<OrderItem> orderItemList = orderNumberMap.get(order.getOrderNumber());
            for (OrderItem orderItem : orderItemList) {
                totalPlatformCommission = Arith.add(totalPlatformCommission, orderItem.getPlatformCommission());
            }
            order.setPlatformCommission(totalPlatformCommission);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delivery(Order order) {
        orderMapper.updateById(order);
        // 消息推送-发货提醒
        Delivery delivery = orderDeliverService.getById(order.getDvyId());
        String dvyName = "";
        if (delivery.getDvyName() != null) {
            dvyName = delivery.getDvyName();
        }
        notifyTemplateService.sendNotifyOfDelivery(order, dvyName, SendType.DELIVERY);
    }


    @Override
    public List<Order> listUnRefundOrderAndOrderItems(Integer orderStatus, DateTime lessThanUpdateTime) {
        return orderMapper.listUnRefundOrderAndOrderItems(orderStatus, lessThanUpdateTime);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrders(List<Order> orders) {
        if (CollectionUtil.isEmpty(orders)) {
            return;
        }
        orderMapper.cancelOrders(orders);
        Set<Long> orderSkuIds = new HashSet<>();
        List<OrderItem> allOrderItems = new ArrayList<>();
        for (Order order : orders) {
            List<OrderItem> orderItems = order.getOrderItems();
            allOrderItems.addAll(orderItems);
            orderSkuIds.addAll(orderItems.stream().map(OrderItem::getSkuId).collect(Collectors.toList()));
            eventPublisher.publishEvent(new CancelOrderEvent(order));
        }
        // 如果是秒杀订单或者数藏盲盒订单也不必还原库存
        if (CollectionUtil.isEmpty(allOrderItems) || OrderType.SECKILL.value().equals(orders.get(0).getOrderType()) || Objects.equals(orders.get(0).getOrderMold(), 3)) {
            return;
        }
        // 解锁库存
        skuStockLockService.unlockStock(orders);

        // 查询出微信支付并且为二维码支付的，失效掉对应支付二维码
//        invalidCode(orders);

    }

    private void invalidCode(List<Order> orders) {
        Set<String> userIds = new HashSet<>();
        Set<String> orderNumbers = new HashSet<>();
        for (Order order : orders) {
            if (Objects.isNull(order.getPayType())) {
                continue;
            }
            // 如果是支付宝支付，或者微信 二维码支付直接使二维码失效
            if (Objects.equals(order.getPayType(), PayType.ALIPAY.value()) ||
                    Objects.equals(order.getPayType(), PayType.WECHATPAY_SWEEP_CODE.value())) {
                userIds.add(order.getUserId());
                orderNumbers.add(order.getOrderNumber());
            }
        }
        if (CollectionUtils.isEmpty(userIds)) {
            return;
        }
        // 如果有重复的payNo，不用失效掉二维码。
        List<PayInfo> payInfoList = payInfoMapper.listByUserIdList(userIds, DateUtil.offsetMinute(new Date(), -35));
        Iterator<PayInfo> iterator = payInfoList.iterator();
        while (iterator.hasNext()) {
            PayInfo payInfo = iterator.next();
            String[] orderNumberList = payInfo.getOrderNumbers().split(",");
            for (String orderNumber : orderNumberList) {
                if (!orderNumbers.contains(orderNumber)) {
                    iterator.remove();
                }
            }
        }
        if (CollectionUtils.isEmpty(payInfoList)) {
            return;
        }
        eventPublisher.publishEvent(new PayManagerEvent(payInfoList));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receiptOrder(List<Order> orders) {
        orderMapper.receiptOrder(orders);
        for (Order order : orders) {
            eventPublisher.publishEvent(new ReceiptOrderEvent(order));
            // 消息推送-用户已确认收货
            notifyTemplateService.sendNotifyByUserRefundDelivery(order, SendType.RECEIPT_ORDER);
        }

    }

    @Override
    public IPage<Order> pageOrdersDetailByOrderParam(Page<Order> page, OrderParam orderParam) {
        Date date = new Date();
        List<Order> orders = orderMapper.listOrdersDetailByOrderParam(new PageAdapter(page), orderParam);
        for (Order order : orders) {
            if (StrUtil.isNotBlank(order.getReceiverName()) && CharUtil.length(order.getReceiverName()) > 8) {
                order.setReceiverName(order.getReceiverName().substring(0, Math.min(8, order.getReceiverName().length() - 1)) + "...");
            }
            if (BooleanUtil.isFalse(permission)) {
                order.setReceiverMobile(order.getReceiverMobile() != null ? PhoneUtil.hideBetween(order.getReceiverMobile()).toString() : null);
                if (Objects.nonNull(order.getUserAddrOrder())) {
                    order.getUserAddrOrder().setMobile(order.getUserAddrOrder().getMobile() != null ? PhoneUtil.hideBetween(order.getUserAddrOrder().getMobile()).toString() : order.getUserAddrOrder().getMobile());
                }
            }
            if (Objects.equals(order.getOrderMold(), 1) && Objects.nonNull(order.getWriteOffEnd()) && DateUtil.compare(order.getWriteOffEnd(), date) < 0) {
                order.setWriteOffCodes(new ArrayList<>());
            }

            // 处理赠品列表
            Map<Long, List<OrderItem>> giveawayMap = order.getOrderItems().stream().filter(orderItem -> Objects.nonNull(orderItem.getGiveawayOrderItemId())).collect(Collectors.groupingBy(OrderItem::getGiveawayOrderItemId));
            if (MapUtil.isNotEmpty(giveawayMap)) {
                Iterator<OrderItem> iterator = order.getOrderItems().iterator();
                while (iterator.hasNext()) {
                    OrderItem orderItem = iterator.next();
                    if (Objects.nonNull(orderItem.getGiveawayOrderItemId())) {
                        iterator.remove();
                    }
                    orderItem.setGiveawayList(giveawayMap.get(orderItem.getOrderItemId()));
                }
            }
        }
        page.setRecords(orders);
        page.setTotal(orderMapper.countOrderDetail(orderParam));
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteOrders(List<Order> orders) {
        orderMapper.deleteOrders(orders);
    }

    @Override
    public OrderCountData getOrderCount(String userId) {
        // 获取普通订单数据
        OrderCountData countData = orderMapper.getOrderCount(userId);
        // 获取退款订单数据
        countData.setRefund(orderRefundMapper.getRefundCount(userId));
        return countData;
    }

    @Override
    public double sumTotalDistributionAmountByOrderItem(List<OrderItem> orderItems) {
        // 订单总分销金额
        double totalDistributionAmount = 0.0;
        if (CollectionUtil.isNotEmpty(orderItems)) {
            for (OrderItem orderItem : orderItems) {
                if (StrUtil.isBlank(orderItem.getDistributionCardNo())) {
                    continue;
                }
                // 如果改订单项已经退款了的话，分销员的佣金就已经回退了，不需要继续算钱
                if (Objects.equals(orderItem.getReturnMoneySts(), SUCCESS.value())) {
                    continue;
                }
                // 分销佣金
                if (orderItem.getDistributionAmount() != null && orderItem.getDistributionAmount() > 0) {
                    totalDistributionAmount = Arith.add(totalDistributionAmount, orderItem.getDistributionAmount());
                }
                // 上级分销佣金
                if (orderItem.getDistributionParentAmount() != null && orderItem.getDistributionParentAmount() > 0) {
                    totalDistributionAmount = Arith.add(totalDistributionAmount, orderItem.getDistributionParentAmount());
                }
            }
        }
        return totalDistributionAmount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeAmount(Order order) {
        Order orderDb = orderMapper.selectOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, order.getOrderId())
                .eq(Order::getOrderNumber, order.getOrderNumber())
        );
        if (!Objects.equals(orderDb.getStatus(), OrderStatus.UNPAY.value())) {
            // 订单状态异常，无法更改订单金额
            throw new YamiShopBindException("yami.order.unrecognized.update");
        }
        Integer changeAmountVersion = 0;
        if (Objects.nonNull(orderDb.getChangeAmountVersion())) {
            changeAmountVersion = orderDb.getChangeAmountVersion() + 1;
        }
        //减少金额
        double amount = 0.00;
        //平台优惠金额
        double platformAmount = 0.00;
        Map<Long, OrderItem> collect = order.getOrderItems().stream().collect(Collectors.toMap(OrderItem::getOrderItemId, orderItem -> orderItem));
        List<OrderItem> orderItemList = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, order.getOrderNumber()));
        for (OrderItem orderItemDb : orderItemList) {
            if (Objects.nonNull(orderItemDb.getGiveawayOrderItemId())) {
                continue;
            }
            OrderItem orderItem = collect.get(orderItemDb.getOrderItemId());
            if (Objects.isNull(orderItem) || Objects.isNull(orderItem.getChageAmount())) {
                continue;
            }

            if (orderItem.getActualTotal() < 0.01 && orderItem.getUseScore() > 0) {
                // 如果金额小于0.01 支付积分大于0则为纯积分支付 此时不进行金额判断
                continue;
            }
            if (orderItem.getChageAmount() >= orderItemDb.getActualTotal() || orderItem.getChageAmount() < 0) {
                // 订单金额必须大于0，或者数据发生变化(请刷新后重试)
                throw new YamiShopBindException("yami.order.amount.check");
            }
            if (Objects.isNull(orderItem.getChageAmount()) || Objects.equals(orderItem.getChageAmount(), 0.00)) {
                continue;
            }
            //修改平台优惠金额
            double playformItemAmount = 0.00;
            if (orderItemDb.getPlatformShareReduce() > 0) {
                //金额减少比例 = 减少金额  % 总金额
                double proportion = Arith.div(orderItem.getChageAmount(), orderItemDb.getProductTotalAmount(), 6);
                //平台优惠金额减少金额 = 减少比例 * 原平台优惠金额
                playformItemAmount = Arith.roundByBanker(Arith.mul(proportion, orderItemDb.getPlatformShareReduce()), 2);
                //平台优惠金额 = 原平台优惠金额 - 对应比例的金额
                orderItemDb.setPlatformShareReduce(Arith.sub(orderItemDb.getPlatformShareReduce(), playformItemAmount));
            }
            // 店铺改价平台优惠减少金额
            orderItemDb.setPlatformShopChangeAmount(playformItemAmount);
            //实际金额 = 原实际金额 - 变化金额
            orderItemDb.setActualTotal(Arith.sub(orderItemDb.getActualTotal(), orderItem.getChageAmount()));
            //总优惠金额 = 变化金额 + 原总优惠金额
            orderItemDb.setShareReduce(Arith.add(orderItem.getChageAmount(), orderItemDb.getShareReduce()));
            // 店铺改价金额为订单项减少的金额
            orderItemDb.setShopChangeFreeAmount(Arith.add(orderItemDb.getShopChangeFreeAmount(), orderItem.getChageAmount()));
            orderItemDb.setChangeAmountVersion(changeAmountVersion);

            amount = Arith.add(amount, orderItem.getChageAmount());
            platformAmount = Arith.add(platformAmount, playformItemAmount);
        }
        // 重新计算佣金
        calculatePlatformCommission(Collections.singletonList(orderDb), orderItemList);
        orderItemService.updateBatchById(orderItemList);
        OrderSettlement orderSettlement = orderSettlementService.getOne(new LambdaQueryWrapper<OrderSettlement>().eq(OrderSettlement::getOrderNumber, order.getOrderNumber()));
        //修改订单信息
        orderDb.setActualTotal(Arith.sub(orderDb.getActualTotal(), amount));
        orderDb.setReduceAmount(Arith.add(orderDb.getReduceAmount(), amount));
        orderDb.setPlatformAmount(Arith.sub(orderDb.getPlatformAmount(), platformAmount));
        orderDb.setShopChangeFreeAmount(orderDb.getShopChangeFreeAmount() + amount);
        // 计算运费变化金额
        if (!Objects.equals(Arith.sub(orderDb.getFreightAmount(), orderDb.getPlatformFreeFreightAmount()), order.getFreightAmount())) {
            if (order.getFreightAmount() < 0) {
                throw new YamiShopBindException("运费金额不能小于0");
            }
            // 根据订单查看是否自营店
            // 判断会员等级是否绑定包邮权益
            if (Objects.equals(orderDb.getShopId(), Constant.MAIN_SHOP)) {
                eventPublisher.publishEvent(new CheckIsMainShopEvent(orderDb));
            }
            double changeFreightAmount = Arith.sub(order.getFreightAmount(), orderDb.getFreightAmount());
            //修改运费信息
            orderDb.setFreightAmount(order.getFreightAmount());
            orderDb.setFreeTransfee(orderDb.getFreeTransfee() + changeFreightAmount);
            orderDb.setActualTotal(Arith.add(orderDb.getActualTotal(), changeFreightAmount));
        }
        orderDb.setChangeAmountVersion(changeAmountVersion);
        orderMapper.updateById(orderDb);
        orderSettlement.setPayAmount(orderDb.getActualTotal());
        orderSettlementService.updateById(orderSettlement);
        // 失效对应的二维码
        invalidCode(Collections.singletonList(orderDb));
    }

    @Override
    public List<Order> getOrderPayInfoByOrderNumber(List<String> orderNumberList) {
        return orderMapper.getOrderPayInfoByOrderNumber(orderNumberList);
    }

    @Override
    public Order getOrderDetailByOrderNumberAndShopId(String orderNumber, Long shopId) {
        Order order = orderMapper.getOrderDetailByOrderNumberAndShopId(orderNumber, shopId);
        if (Objects.isNull(order) || CollUtil.isEmpty(order.getOrderItems())) {
            return order;
        }
        List<OrderRefund> orderRefundList = orderRefundMapper.getProcessingOrderRefundByOrderId(order.getOrderId());
        if (CollUtil.isEmpty(orderRefundList)) {
            return order;
        }

        order.setRefundType(orderRefundList.get(0).getRefundType());

        // 整单退款
        if (Objects.equals(order.getRefundType(), RefundType.ALL.value())) {
            OrderRefund orderRefund = orderRefundList.get(0);
            for (OrderItem orderItem : order.getOrderItems()) {
                orderItem.setRefundId(orderRefund.getRefundId());
                orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
            }
            return order;
        }
        // 单项退款
        Map<Long, OrderRefund> refundMap = orderRefundList.stream().collect(Collectors.toMap(OrderRefund::getOrderItemId, o -> o));
        for (OrderItem orderItem : order.getOrderItems()) {
            OrderRefund orderRefund = refundMap.get(orderItem.getOrderItemId());
            if (Objects.nonNull(orderRefund)) {
                orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                orderItem.setRefundId(orderRefund.getRefundId());
            }
        }
        return order;
    }

    @Override
    public Map<Long, Integer> getOrderItemMap(Long orderId) {
        List<OrderRefund> orderRefunds = orderRefundMapper.selectList(new LambdaQueryWrapper<OrderRefund>()
                .eq(OrderRefund::getOrderId, orderId)
                .lt(OrderRefund::getReturnMoneySts, 6)
                .gt(OrderRefund::getReturnMoneySts, 0)
        );
        Map<Long, Integer> map = Maps.newHashMap();

        for (OrderRefund orderRefund : orderRefunds) {
            if (orderRefund.getRefundType() == 1) {
                map.put(0L, orderRefund.getReturnMoneySts());
                return map;
            }
            map.put(orderRefund.getOrderItemId(), orderRefund.getReturnMoneySts());
        }
        return map;
    }

    @Override
    public Integer countByOrderNumber(String orderNumber) {
        return orderMapper.countByOrderNumber(orderNumber);
    }

    @Override
    public UnDeliveryOrderExcelVO getOrderAndOrderItemsByOrderNumberAndShopId(String orderNumber, Long shopId) {
        return orderMapper.getOrderAndOrderItemsByOrderNumberAndShopId(orderNumber, shopId);
    }

    @Override
    public List<Order> getOrdersStatus(List<String> orderNumbers) {
        List<Order> orderList = list(new LambdaQueryWrapper<Order>()
                .select(Order::getOrderNumber, Order::getStatus, Order::getOrderType, Order::getActualTotal, Order::getUserId, Order::getCreateTime).in(Order::getOrderNumber, orderNumbers));
        for (String orderNumber : orderNumbers) {
            boolean hasOrderNumber = false;
            for (Order orderStatusBO : orderList) {
                if (StrUtil.equals(orderStatusBO.getOrderNumber(), orderNumber)) {
                    hasOrderNumber = true;
                    break;
                }
            }
            if (!hasOrderNumber) {
                Order orderStatusBO = new Order();
                orderStatusBO.setOrderNumber(orderNumber);
                orderList.add(orderStatusBO);
            }
        }
        return orderList;
    }

    @Override
    public OrderAmountVO getOrdersAmountAndIfNoCancel(List<String> orderNumbers, Integer payType) {
        List<Order> ordersStatus = getOrdersStatus(orderNumbers);
        if (CollUtil.isEmpty(ordersStatus)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }

        for (Order order : ordersStatus) {
            if (!Objects.equals(order.getStatus(), OrderStatus.UNPAY.value())) {
                // 支付失败，订单不在未支付状态
                throw new YamiShopBindException("yami.order.pay.fail");
            }
            if (Objects.isNull(order.getStatus()) || Objects.equals(order.getStatus(), OrderStatus.CLOSE.value())) {
                // 订单已关闭
                throw new YamiShopBindException("yami.order.is.closed");
            }
            // 普通订单创建时间经过限定订单超时分钟，如果为true则早于当前时间表示过期，抛出异常
            boolean isExpired = !DateUtil.offsetMinute(order.getCreateTime(), Constant.ORDER_MAX_TIME).after(new Date());
            if (isExpired) {
                // 秒杀订单已经过期，无法进行支付
                throw new YamiShopBindException("yami.order.expired");
            }
            // 如果是秒杀订单,还需判断秒杀订单有没有过期
            if (Objects.equals(order.getOrderType(), OrderType.SECKILL.value())) {
                applicationContext.publishEvent(new CheckSecKillOrderEvent(order));
            }
            // 如果是团购订单,还需判断团购订单有没有过期
            if (Objects.equals(order.getOrderType(), OrderType.GROUP.value())) {
                applicationContext.publishEvent(new CheckGroupOrderEvent(order));
            }
            order.setPayType(payType);
            update(order, Wrappers.lambdaUpdate(Order.class).eq(Order::getOrderNumber, order.getOrderNumber()));
        }
        return orderMapper.getOrdersActualAmount(orderNumbers);
    }

    @Override
    public void updateByToPaySuccess(List<String> orderNumbers, Integer payType) {
        orderMapper.updateByToPaySuccess(orderNumbers, payType);
    }

    @Override
    public String exSubmit(ExchangeOrderDTO exchangeOrderDTO, String userId) {
//        UserAddrOrder userAddrOrder = new UserAddrOrder();
//        // 使用雪花算法生成的订单号
//        String orderNumber = String.valueOf(snowflake.nextId());
//        Order order = new Order();
//        //0 获取默认地址
//        UserAddr userAddr = new UserAddr();
//        if (exchangeOrderDTO.getAddrId() == 0) {
//            userAddr = userAddrService.getDefaultUserAddr(userId);
//        } else {
//            userAddr = userAddrService.getById(exchangeOrderDTO.getAddrId());
//        }
//        // 把订单地址保存到数据库
//        userAddrOrder = BeanUtil.map(userAddr, UserAddrOrder.class);
//        if (userAddrOrder == null) {
//            // 请填写收货地址
//            throw new BclmShopBindException("bclm.delivery.address");
//        }
//        userAddrOrder.setCreateTime(new Date());
//        userAddrOrder.setUserId(userId);
//        userAddrOrderService.save(userAddrOrder);
//        //自提订单的地址信息
//        Long orderSelfId = null;
//        if (Objects.equals(exchangeOrderDTO.getDvyType(), DvyType.STATION.value())) {
//            eventPublisher.publishEvent(new OrderSelfStationEvent(exchangeOrderDTO.getStationId(), exchangeOrderDTO.getShopId(), orderNumber,exchangeOrderDTO.getStationUserMobile(),exchangeOrderDTO.getStationUserName(),exchangeOrderDTO.getStationTime(),orderSelfId));
//            order.setDvyId(exchangeOrderDTO.getStationId());
//            order.setAddrOrderId(orderSelfId);
//        }else{
//            order.setAddrOrderId(userAddrOrder.getAddrOrderId());
//        }
//        //商品信息
//        Product bySpuId = productService.getById(exchangeOrderDTO.getSpuId());
//        //规格信息
//        Sku bySkuId = skuService.getById(exchangeOrderDTO.getSkuId());
//
//        order.setProdName(bySpuId.getProdName());
//        order.setUserId(userId);
//        order.setOrderType(OrderType.EXCHANGE.value());  // 5 兑换订单
//        order.setTotal(bySpuId.getPrice()); //金额
//        order.setStatus(OrderStatus.PADYED.value());
//        order.setIsPayed(0);
//        order.setDeleteStatus(0);
//        order.setShopId(exchangeOrderDTO.getShopId());
//        order.setOrderNumber(orderNumber);
//        order.setDvyType(exchangeOrderDTO.getDvyType());
//        order.setCreateTime(new DateTime());
//        order.setProductNums(exchangeOrderDTO.getCount());
//        order.setActualTotal(bySpuId.getPrice());
//        order.setChangeAmountVersion(0);
//        order.setOrderMold(2);
//        order.setProductNums(exchangeOrderDTO.getCount());
//
//
//        orderService.save(order);
//
//        OrderItem orderItem = new OrderItem();
//        orderItem.setOrderNumber(orderNumber);
//        orderItem.setProdNameCn(bySpuId.getProdName());
//        orderItem.setProdName(bySpuId.getProdName());
//        orderItem.setPic(bySpuId.getPic());
//        orderItem.setShopId(bySpuId.getShopId());
//        orderItem.setUserId(userId);
//        orderItem.setRecTime(new Date());
//        orderItem.setSkuId(exchangeOrderDTO.getSkuId());
//        orderItem.setProdId(exchangeOrderDTO.getSpuId());
//        orderItem.setProdCount(exchangeOrderDTO.getCount());
//        orderItem.setPrice(bySpuId.getPrice());
//        double total = bySpuId.getPrice() * exchangeOrderDTO.getCount();
//        orderItem.setProductTotalAmount(total);
//        orderItem.setCommSts(0);
//        orderItem.setSkuName(bySkuId.getSkuName());
//        orderItem.setShareReduce(0.00);
//        orderItem.setActualTotal(bySpuId.getPrice());
//        orderItemService.save(orderItem);
//        //添加币消耗记录
//        for(int i=0;i<exchangeOrderDTO.getOrderExchangeNfts().size();i++){
//            exchangeOrderDTO.getOrderExchangeNfts().get(i).setOrderNumber(orderNumber);
//        }
//        orderExchangeNftMapper.saves(exchangeOrderDTO.getOrderExchangeNfts());
//        return orderNumber;
        return null;
    }
    @Override
    public Order createOrder(RedOrderDto dto) {
        Order order = new Order();
        order.setShopId(0l);
        order.setTotal(dto.getTotalAmount());
        order.setUserId(dto.getUserId());
        order.setOrderType(RED.value());
        order.setOrderNumber(String.valueOf(snowflake.nextId()));
        order.setIsPayed(1);
        order.setDeleteStatus(0);
        order.setStatus(SUCCESS.value());
        order.setCreateTime(new DateTime());
        order.setActualTotal(dto.getTotalAmount());
        order.setChangeAmountVersion(0);
        this.save(order);
        OrderSettlement orderSettlement = new OrderSettlement();
        orderSettlement.setUserId(dto.getUserId());
        orderSettlement.setCreateTime(new Date());
        orderSettlement.setOrderNumber(order.getOrderNumber());
        orderSettlement.setPayAmount(order.getTotal());
        orderSettlement.setPayStatus(0);
        orderSettlement.setPayType(dto.getPayType());
        orderSettlement.setVersion(0);
        orderSettlement.setPayScore(0l);
        orderSettlementMapper.insert(orderSettlement);
        return order;
    }

    @Override
    public Order getOrderAndOrderItemByOrderNumber(String orderNumber) {
        return orderMapper.getOrderAndOrderItemByOrderNumber(orderNumber);
    }
    @Override
    public Order getOrderAndOrderItemByOrderId(Long orderId) {
        return orderMapper.getOrderAndOrderItemByOrderId(orderId);
    }
    @Override
    public void getOrderItemRefundStatus(Order order) {
        if (Objects.nonNull(order.getRefundStatus()) && !Objects.equals(order.getRefundStatus(), RefundStatusEnum.DISAGREE.value())) {
            List<OrderRefund> processingOrderRefundByOrderId = orderRefundMapper.getProcessingOrderRefundByOrderId(order.getOrderId());
            for (OrderRefund orderRefund : processingOrderRefundByOrderId) {
                //整单退款
                if (orderRefund.getRefundType() == 1) {
                    for (OrderItem orderItem : order.getOrderItems()) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                    break;
                }
                // 单项退款，每个单号都不一样
                for (OrderItem orderItem : order.getOrderItems()) {
                    if (Objects.equals(orderItem.getOrderItemId(), orderRefund.getOrderItemId())) {
                        orderItem.setReturnMoneySts(orderRefund.getReturnMoneySts());
                    }
                }
            }
        }
    }


    @Override
    public IPage<Order> pageByUserId(PageParam<Order> page, String userId) {
        return orderMapper.getPageByUserId(page, userId);
    }

    @Override
    public List<Order> listPendingSettlementOrders(Integer orderStatus, Date startTime) {
        return orderMapper.listPendingSettlementOrders(orderStatus, startTime);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderCommissionSettlement(List<Order> orders) {
        List<Long> orderIds = orders.stream().map(Order::getOrderId).collect(Collectors.toList());
        if (CollUtil.isEmpty(orderIds)) {
            return;
        }
        List<Order> list = list(new LambdaQueryWrapper<Order>()
                .in(Order::getOrderId, orderIds)
                .eq(Order::getStatus, OrderStatus.SUCCESS.value())
        );
        orderIds = list.stream().map(Order::getOrderId).collect(Collectors.toList());
        if (CollUtil.isEmpty(orderIds)) {
            return;
        }
        // 众所周知，结算之后是不能改变状态的
        int updateStats = orderMapper.settledOrder(list);
        if (updateStats == 0) {
            return;
        }
        eventPublisher.publishEvent(new OrderSettlementEvent(list));
    }


    @Override
    public IPage<MyOrderDto> orderListByStatus(PageParam<MyOrderDto> page, Integer status, Long stationId) {
        List<MyOrderDto> myOrderDtos = orderMapper.orderListByStatusAndStationId(new PageAdapter(page), status, stationId);
        for (MyOrderDto myOrderDto : myOrderDtos) {
            for (MyOrderItemDto orderItemDto : myOrderDto.getOrderItemDtos()) {
                if (Objects.equals(myOrderDto.getOrderMold(), 1)) {
                    orderItemDto.setProdCount(myOrderDto.getProductNums());
                }
            }
        }
        page.setRecords(myOrderDtos);
        List<MyOrderDto> orderDtoList = page.getRecords();
        for (MyOrderDto myOrderDto : orderDtoList) {
            if (StrUtil.isBlank(myOrderDto.getShopName())) {
                myOrderDto.setShopName(Constant.PLATFORM_SHOP_NAME);
            }
        }
        page.setTotal(orderMapper.countByStatusAndStationId(status, stationId));
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean orderStationByOrderNumber(List<String> orderNumberList, String userId, Long stationId) {
        if (CollUtil.isEmpty(orderNumberList)) {
            // 请选择最少一个需要自提的订单
            throw new YamiShopBindException("yami.order.need.station");
        }
        List<Order> orderList = orderMapper.getStationOrderByOrderNumbers(orderNumberList, userId, null);
        Order orderParam = new Order();
        if (CollectionUtils.isEmpty(orderList)) {
            // 订单不存在
            throw new YamiShopBindException("yami.order.no.exist");
        }
        List<String> updateOrderNumbers = new ArrayList<>(16);
        for (Order order : orderList) {
            if (Objects.isNull(order)) {
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            orderParam = order;
            if (Objects.equals(order.getOrderMold(), 1)) {
                orderVirtualInfoService.orderWriteOffByOrderNumber(null, order, stationId);
                continue;
            }
            // 如果不是自提订单且不是核销订单就直接报错，如果是扫商家码进来的就不需要自提点id
            if (!Objects.equals(order.getDvyType(), DvyType.STATION.value()) || (!Objects.equals(order.getDvyId(), stationId) && !Objects.equals(stationId, null))) {
                // 订单不存在
                throw new YamiShopBindException("yami.order.no.exist");
            }
            boolean isRefund = Objects.equals(order.getRefundStatus(), RefundStatusEnum.APPLY.value())
                    || Objects.equals(order.getRefundStatus(), RefundStatusEnum.SUCCEED.value());
            if (Objects.nonNull(order.getRefundStatus()) && isRefund) {
                // 订单退款中，无法自提
                throw new YamiShopBindException(I18nMessage.getMessage("yami.order") + order.getOrderNumber() + I18nMessage.getMessage("yami.order.station.check"));
            }
            if (!Objects.equals(order.getStatus(), OrderStatus.PADYED.value())) {
                // 订单已提货
                throw new YamiShopBindException(I18nMessage.getMessage("yami.order") + order.getOrderNumber() + I18nMessage.getMessage("yami.order.station.finish"));
            }
            order.setStatus(OrderStatus.CONSIGNMENT.value());
            order.setDvyTime(new Date());
            order.setUpdateTime(new Date());
            updateOrderNumbers.add(order.getOrderNumber());
        }
        if (Objects.isNull(stationId)) {
            stationId = orderParam.getDvyId();
        }
        Station station = stationService.getById(stationId);
//        if (!Objects.equals(station.getStatus(), StationStatusEnum.OPEN.value())) {
//            // 该自提点未在营业状态
//            throw new YamiShopBindException("yami.shop.station.not.open");
//        }
        String stationName = "";
        if (Objects.nonNull(station)) {
            stationName = station.getStationName();
        }

        updateBatchById(orderList);
        // 修改订单对应的商品，将状态修改全部已发货
        if (!CollectionUtils.isEmpty(updateOrderNumbers)) {
            Integer allDelivery = 0;
            orderItemService.update(new LambdaUpdateWrapper<OrderItem>()
                    .set(OrderItem::getStatus, allDelivery)
                    .in(OrderItem::getOrderNumber, updateOrderNumbers));
        }
        // 消息推送-自提点核销通知
        if (orderList.size() > 1) {
            orderParam.setOrderNumber(orderParam.getOrderNumber() + "......");
        }
        notifyTemplateService.writeOffOrder(stationName, orderParam);
        return true;
    }

    @Override
    public IPage<Order> pageByUserIdAndShopId(PageParam<Order> page, String userId, Long shopId) {
        return orderMapper.getPageByUserIdAndShopId(page, userId, shopId);
    }

    @Override
    public OrderShopDto orderDetail(String orderNumber, String userId, Long stationId) {

        OrderShopDto orderShopDto = orderMapper.orderDetailByOrderNumberList(orderNumber);
        // 订单项
        List<OrderItem> orderItemList = orderItemService.list(new LambdaQueryWrapper<OrderItem>().eq(OrderItem::getOrderNumber, orderNumber));
        List<OrderItemDto> orderItems = BeanUtil.mapAsList(orderItemList, OrderItemDto.class);
        // 订单项赠品
        Map<Long, List<OrderItem>> giveawayMap = orderItemList.stream().filter(orderItem -> Objects.nonNull(orderItem.getGiveawayOrderItemId())).collect(Collectors.groupingBy(OrderItem::getGiveawayOrderItemId));


        // 插入平台名称、订单项列表
        // 设置平台店铺名称
        if (Objects.equals(orderShopDto.getShopId(), Constant.PLATFORM_SHOP_ID)) {
            orderShopDto.setShopName(Constant.PLATFORM_SHOP_NAME);
        }
        orderShopDto.setOrderItemDtos(orderItems);
        //计算订单使用积分
        Long score = 0L;
        double total = 0.0;
        Integer totalNum = 0;
        for (OrderItemDto orderItem : orderItems) {
            score += orderItem.getUseScore();
            total = Arith.add(total, orderItem.getProductTotalAmount());
            totalNum += orderItem.getProdCount();
            if (giveawayMap.containsKey(orderItem.getOrderItemId())) {
                orderItem.setGiveawayList(giveawayMap.get(orderItem.getOrderItemId()));
            }
        }
        orderShopDto.setOrderScore(score);
        orderShopDto.setTotal(total);
        orderShopDto.setTotalNum(totalNum);

        orderShopDto.setOrderItemDtos(orderItems);

        return orderShopDto;
    }

    @Override
    public Integer getOrderByuserId(Long prodId, String userId) {
        Integer orderByuserId = orderMapper.getOrderByuserId(prodId, userId);
        return orderByuserId;
    }

    @Override
    public Integer getOrderPurchaseCount(String userId, Long prodId, Long activityId) {
        Integer orderPurchaseCount = orderMapper.getOrderPurchaseCount(userId, prodId,activityId);
        return orderPurchaseCount;
    }

    @Override
    public OrderUnpaidInfoDto getOrderUnpaidInfoDto(Long prodId, String userId) {
        OrderUnpaidInfoDto orderUnpaidInfoDto = orderMapper.getOrderUnpaidInfoDto(prodId, userId);
        return orderUnpaidInfoDto;
    }

    @Override
    public Integer getOrderPurchaseCountByDate(String userId, Long prodId, Date startTime, Date endTime) {
        Integer orderPurchaseCount = orderMapper.getOrderPurchaseCountByDate(userId, prodId, startTime, endTime);
        return orderPurchaseCount;
    }
}
